package com.zzyl.common.utils.pdf;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 增强版PDF读取工具类，解决EOFException等常见错误
 */
public class PdfReaderUtil {
    private static final Logger logger = LoggerFactory.getLogger(PdfReaderUtil.class);
    private static final int MIN_PDF_SIZE = 1024; // 最小PDF文件大小(字节)
    private static final byte[] PDF_HEADER = "%PDF-".getBytes(); // PDF文件头标识

    /**
     * 从PDF文件中读取文本内容
     *
     * @param filePath PDF文件路径
     * @return 提取的文本字符串，发生错误时返回具体错误信息
     */
    public static String readPdfToString(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            return "错误：PDF文件路径不能为空";
        }

        try {
            Path path = Paths.get(filePath);
            // 验证文件基本信息
            String validateResult = validatePdfFile(path);
            if (validateResult != null) {
                return validateResult;
            }

            // 读取文件内容
            return readPdfContent(new FileInputStream(filePath));
        } catch (Exception e) {
            logger.error("读取PDF文件异常", e);
            return "读取失败：" + e.getMessage();
        }
    }

    /**
     * 从输入流中读取PDF文本内容
     *
     * @param inputStream PDF文件的输入流
     * @return 提取的文本字符串，发生错误时返回具体错误信息
     */
    public static String readPdfToString(InputStream inputStream) {
        if (inputStream == null) {
            return "错误：输入流不能为空";
        }

        try {
            // 包装输入流，支持mark和reset操作
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            // 验证PDF文件头
            if (!validatePdfHeader(bufferedInputStream)) {
                return "错误：不是有效的PDF文件";
            }
            // 重置输入流到起始位置
            bufferedInputStream.reset();

            return readPdfContent(bufferedInputStream);
        } catch (Exception e) {
            logger.error("从输入流读取PDF异常", e);
            return "读取失败：" + e.getMessage();
        }
    }

    /**
     * 验证PDF文件的有效性
     */
    private static String validatePdfFile(Path path) throws IOException {
        // 检查文件是否存在
        if (!Files.exists(path)) {
            return "错误：文件不存在";
        }
        // 检查是否是文件
        if (!Files.isRegularFile(path)) {
            return "错误：不是有效的文件";
        }
        // 检查文件大小
        long fileSize = Files.size(path);
        if (fileSize < MIN_PDF_SIZE) {
            return "错误：文件过小，可能不是有效的PDF或文件已损坏";
        }
        // 检查文件头
        try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(path))) {
            if (!validatePdfHeader(bis)) {
                return "错误：不是有效的PDF文件";
            }
        }
        return null;
    }

    /**
     * 验证PDF文件头标识
     */
    private static boolean validatePdfHeader(BufferedInputStream bis) throws IOException {
        // 标记当前位置，用于后续重置
        bis.mark(PDF_HEADER.length + 1);
        byte[] header = new byte[PDF_HEADER.length];
        int read = bis.read(header);
        // 检查是否读取到足够的字节且与PDF头匹配
        return read == PDF_HEADER.length && java.util.Arrays.equals(header, PDF_HEADER);
    }

    /**
     * 读取PDF内容的核心方法
     */
    private static String readPdfContent(InputStream inputStream) {
        PDDocument document = null;
        try {
            // 增加PDFBox配置，提高容错性
            document = PDDocument.load(inputStream); // 第二个参数表示启用严格模式

            // 检查文档是否被加密
            if (document.isEncrypted()) {
                return "错误：PDF文档已加密，无法读取内容";
            }

            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document);
        } catch (EOFException e) {
            logger.error("PDF文件不完整或已损坏", e);
            return "错误：PDF文件不完整或已损坏 - " + e.getMessage();
        } catch (IOException e) {
            logger.error("读取PDF内容时发生错误", e);
            return "错误：读取PDF内容失败 - " + e.getMessage();
        } finally {
            // 确保文档资源被释放
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    logger.warn("关闭PDF文档时发生错误", e);
                }
            }
            // 关闭输入流
            try {
                inputStream.close();
            } catch (IOException e) {
                logger.warn("关闭输入流时发生错误", e);
            }
        }
    }
}



    